package TrainModel;

import static org.junit.Assert.*;
import TrainController.*;
import TrackModel.*;
import Utilities.Message;

import org.junit.Test;

public class TrainController_TrainModel_Combined
{
	@Test
	public void SpeedRegulation1()
	{
		String theBlockString = "1|1|1000000000|0|55|0.5|285:323|24:43|0|0|13|0";
		String[] parts = theBlockString.split("\\|");
		Block megaBlock = new Block(parts);
		megaBlock.setRailTemperature(70);
		
		TrainModel tm = new TrainModel(0, 1000);
		tm.setCurrentBlock(megaBlock);
		tm.toggleConductor();
		TrainController tc = tm.trainControl;
		Message mSpeed = new Message("T 0 | S 20");
		Message mAuth= new Message("T 0 | A 100");
		
		tm.setMessage(mSpeed);
		tm.tick();
		tc.tick();
		tm.setMessage(mAuth);
		tm.tick();
		tc.tick();
		
		for( int i = 0; i < 1000; i++)
		{
			tm.tick();
			tc.tick();
		}
		
		double dTolerance = 1;
		double dActualSpeed = tm.getSpeed()*2.23694;
		assertTrue( Math.abs(dActualSpeed - 20) < dTolerance);
	}
	
	@Test
	public void BrakeFailure()
	{
		String theBlockString = "1|1|1000000000|0|55|0.5|285:323|24:43|0|0|13|0";
		String[] parts = theBlockString.split("\\|");
		Block megaBlock = new Block(parts);
		megaBlock.setRailTemperature(70);
		
		TrainModel tm = new TrainModel(0, 1000);
		tm.setCurrentBlock(megaBlock);
		tm.toggleConductor();
		TrainController tc = tm.trainControl;
		Message mSpeed = new Message("T 0 | S 20");
		Message mAuth= new Message("T 0 | A 100");
		
		tm.setMessage(mSpeed);
		tm.tick();
		tc.tick();
		tm.setMessage(mAuth);
		tm.tick();
		tc.tick();
		
		for( int i = 0; i < 100; i++)
		{
			tm.tick();
			tc.tick();
		}
		
		for( int i = 0; i < 4; i++)
		{
			tm.initiateBrakeFailure();
			tm.tick();
			tc.tick();
		}
		
		assertTrue(tm.getBrakeFailure().equals("FAILURE"));
		assertTrue(tm.getCurrentEBrake().equals("ON"));
	}
	
	@Test
	public void EngineFailure()
	{
		String theBlockString = "1|1|1000000000|0|55|0.5|285:323|24:43|0|0|13|0";
		String[] parts = theBlockString.split("\\|");
		Block megaBlock = new Block(parts);
		megaBlock.setRailTemperature(70);
		
		TrainModel tm = new TrainModel(0, 1000);
		tm.setCurrentBlock(megaBlock);
		tm.toggleConductor();
		TrainController tc = tm.trainControl;
		Message mSpeed = new Message("T 0 | S 20");
		Message mAuth= new Message("T 0 | A 100");
		
		tm.setMessage(mSpeed);
		tm.tick();
		tc.tick();
		tm.setMessage(mAuth);
		tm.tick();
		tc.tick();
		
		for( int i = 0; i < 100; i++)
		{
			tm.tick();
			tc.tick();
		}
		
		for( int i = 0; i < 4; i++)
		{
			tm.initiateEngineFailure();
			tm.tick();
			tc.tick();
			tm.getCurrentEBrake();
		}
		
		assertTrue(tm.getEngineFailure().equals("FAILURE"));
		assertTrue(tm.getCurrentEBrake().equals("ON"));
		assertTrue(tc.reportEngineFailure() == true);
	}
	
	@Test
	public void EngineAndBrakeFailure()
	{
		String theBlockString = "1|1|1000000000|0|55|0.5|285:323|24:43|0|0|13|0";
		String[] parts = theBlockString.split("\\|");
		Block megaBlock = new Block(parts);
		megaBlock.setRailTemperature(70);
		
		TrainModel tm = new TrainModel(0, 1000);
		tm.setCurrentBlock(megaBlock);
		tm.toggleConductor();
		TrainController tc = tm.trainControl;
		Message mSpeed = new Message("T 0 | S 20");
		Message mAuth= new Message("T 0 | A 100");
		
		tm.setMessage(mSpeed);
		tm.tick();
		tc.tick();
		tm.setMessage(mAuth);
		tm.tick();
		tc.tick();
		
		for( int i = 0; i < 100; i++)
		{
			tm.tick();
			tc.tick();
		}
		
		for( int i = 0; i < 4; i++)
		{
			tm.initiateEngineFailure();
			tm.initiateBrakeFailure();
			tm.tick();
			tc.tick();
		}
		
		assertTrue(tm.getEngineFailure().equals("FAILURE"));
		assertTrue(tm.getBrakeFailure().equals("FAILURE"));
		assertTrue(tm.getCurrentEBrake().equals("ON"));
		assertTrue(tc.reportEngineFailure() == true);
		assertTrue(tc.reportBrakeFailure() == true);
	}

	@Test
	public void StationArrival()
	{
		String tBS = "1|1|100|0|55|0.5|285:323|24:43|0|0|2|0";
		String[] prts = tBS.split("\\|");
		Block currBlock = new Block(prts);
		
		String theBlockString = "1|1|100|0|55|0.5|285:323|24:43|0|0|2|0";
		String[] parts = theBlockString.split("\\|");
		Block b1 = new Block(parts);
		
		String theBlockString2 = "2|1|100|0|55|0.5|285:323|24:43|0|1|3|0";
		String[] parts2 = theBlockString2.split("\\|");
		Block b2 = new Block(parts2);
		
		String theBlockString3 = "3|1|100|0|55|0.5|285:323|24:43|0|0|1|Pioneer|0";
		String[] parts3 = theBlockString3.split("\\|");
		Block b3 = new Block(parts3);
		
		TrainModel tm = new TrainModel(0, 1000);
		tm.setCurrentBlock(b1);
		System.out.println("WILLY WONKA HAS A WEINER"+b1.hasTrain);
		tm.toggleConductor();
		TrainController tc = tm.trainControl;
		Message mSpeed = new Message("T 0 | S 20");
		Message mAuth= new Message("T 0 | A 100");
		double disp = 0;
		tm.setMessage(mSpeed);
		tm.tick();
		tc.tick();
		tm.setMessage(mAuth);
		tm.tick();
		tc.tick();
		
		boolean bDoorsOpened = false;
		boolean bAnnounced = false;
		boolean bDoorsClosedAgain = false;
		
		for( int i = 0; i < 100000; i++)
		{
			// Hack because we're not actually on a track
			if(b2.hasTrain == true)
			{
				tm.setTransponderSignal("Pioneer");
			}
			tm.tick();
			tc.tick();
			disp = disp+tm.getSpeed();
			
			//Kludged to permit a three block circuit
			if(disp > tm.getCurrentBlock().getLength())
			{
				disp = 0;
				
				if(currBlock.equals(b1))
				{
				tm.setCurrentBlock(b2);
				currBlock = b2;
				}
				else if(currBlock.equals(b2))
				{
					tm.setCurrentBlock(b3);
					currBlock = b3;
				}
				else
				{
					tm.setCurrentBlock(b1);
					currBlock = b1;
				}
			}
			if(tm.getDoorState().equals("OPEN"))
			{
				bDoorsOpened = true;
			}
			
			if(tm.getAnnouncements() != null)
			{
				bAnnounced = true;
			}
			
			if( bDoorsOpened && tm.getDoorState().equals("CLOSED") )
			{
				bDoorsClosedAgain = true;
			}
		}
		
		assertTrue(bDoorsOpened);
		assertTrue(bAnnounced);
		assertTrue(bDoorsClosedAgain);
		
		
	}
	
}
